Skip to content

fix: recreate pnpm symlinks as junctions on Windows in copyTracedFiles#1185

Open
joshua92y wants to merge 1 commit into
opennextjs:mainfrom
joshua92y:fix/windows-pnpm-symlink-junction
Open

fix: recreate pnpm symlinks as junctions on Windows in copyTracedFiles#1185
joshua92y wants to merge 1 commit into
opennextjs:mainfrom
joshua92y:fix/windows-pnpm-symlink-junction

Conversation

@joshua92y

Copy link
Copy Markdown

Summary

Fixes #1184

On Windows, copyTracedFiles recreates pnpm directory symlinks from the raw readlinkSync value. Per the Node docs, symlinkSync without a type autodetects from the target — and falls back to 'file' when the target does not exist. Since entries are copied in traversal order, the relative target inside the output mirror frequently does not exist yet at link-creation time, producing a file-type symlink pointing at a directory. Windows cannot traverse those, so esbuild later fails with Cannot read directory ...: Access is denied / Could not resolve "styled-jsx".

Change

On win32, recreate the link as a junction whose target is the raw symlink value resolved against the destination's parent directory — semantically identical to what the relative symlink means on Linux (it points into the mirrored output structure):

  • junctions only apply to directories (every pnpm link recreated here is one)
  • no admin rights / Developer Mode required
  • resolve lazily, so the link is valid once the target directory is populated later in the copy
  • \\?\ -prefixed absolute targets (as returned by readlinkSync for junctions) are handled

Non-Windows behavior is unchanged.

Validation

  • packages/tests-unit/tests/build/copyTracedFiles.test.ts — 9/9 passing
  • pnpm --filter @opennextjs/aws build (tsc) and biome check pass
  • Verified as a patch against @opennextjs/aws 4.0.2 on three real Next.js 16 apps on Windows 11 (pnpm nodeLinker: isolated ×2, hoisted ×1): builds reach "Worker saved" with no esbuild errors, and all three are deployed to Cloudflare Workers serving HTTP 200 in production.

A changeset (patch) is included.

🤖 Generated with Claude Code

…yTracedFiles

On Windows, recreating a pnpm directory symlink from the raw readlinkSync
value produces a file-type symlink when the target does not exist yet
(Node autodetects the type and falls back to "file"), which Windows cannot
traverse as a directory. esbuild then fails with
"Cannot read directory ...: Access is denied" / could not resolve errors.

Create a junction instead, with the raw target resolved against the
destination parent directory - semantically identical to what the relative
symlink means on Linux. Junctions only apply to directories, need no admin
rights or Developer Mode, and resolve lazily once the target is populated.

Fixes opennextjs#1184

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: fb13e04

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@opennextjs/aws Patch
app-pages-router Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

copyTracedFiles recreates pnpm symlinks as broken links on Windows (esbuild "Cannot read directory: Access is denied")

1 participant